package com.ivanceras.server.util;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import com.ivanceras.shared.dao.DAO_Ad_column;
import com.ivanceras.shared.dao.DAO_Ad_element;
import com.ivanceras.shared.dao.DAO_Ad_reference;
import com.ivanceras.shared.dao.DAO_Ad_table;
import com.ivanceras.shared.db.EntityManager;
import com.ivanceras.shared.db.Filter;
import com.ivanceras.shared.db.ModelDef;
import com.ivanceras.shared.exception.DatabaseException;

/**
 * This will extract the table meta then save the information into the Ad_table
 * @author lee
 *
 */
public class MetaTableExtractor {

	static BigDecimal referenceId = new BigDecimal(0);
	static BigDecimal elementId = new BigDecimal(0);

	static void truncateAppDtables(EntityManager em) throws DatabaseException{
		String[] schemas = {"appd",      "appd",     "appd",         "appd",   "appd",     "appd",     "appd"};
		String[] tables =  {"ad_column", "ad_field", "ad_reference", "ad_tab", "ad_table", "ad_window","ad_element" };
			for(int i = 0; i < tables.length; i++){
				String sch = schemas[i];
				String tbl = tables[i];
				truncateTable(em, sch, tbl);
			}
	}

	static void truncateTable(EntityManager em, String schema, String table) throws DatabaseException{
		ModelDef model = new ModelDef();
		model.setNamespace(schema);
		model.setModelName(table);
		em.empty(model);
	}

	public static void extractToAppD(EntityManager em, String user, String tablePattern) throws DatabaseException{
		em.beginTransaction();
		List<ModelDef> modelList = DAOGenerator.getTableDefinitions(em, user, tablePattern);
		BigDecimal tableId = new BigDecimal(0);
		BigDecimal columnId = new BigDecimal(0);
		for(ModelDef model : modelList){
			String tableName = model.getModelName().toLowerCase();
			DAO_Ad_table daoTable = new DAO_Ad_table();
			tableId = tableId.add(new BigDecimal(1));
			daoTable.setAd_table_id(tableId);
			daoTable.setTablename(tableName);
			daoTable.setIsactive("Y");
			daoTable.setName(CStringUtils.beautify(tableName));
			daoTable.setCreated(new Date());
			daoTable.setUpdated(new Date());
			daoTable.setEntitytype("M");
			daoTable.setIshighvolume("N");

			em.insert(daoTable);

			//extract the columns
			String[] attributes = model.getAttributes();
			String[] dataTypes = model.getDataTypes();
			for(int i = 0; i < attributes.length; i++){
				String attr = attributes[i];
				String dt = dataTypes[i];
				DAO_Ad_column daoColumn = new DAO_Ad_column();
				columnId = columnId.add(new BigDecimal(1));
				String columnName = attr.toLowerCase();
				daoColumn.setAd_column_id(columnId);
				daoColumn.setColumnname(columnName);
				daoColumn.setName(CStringUtils.beautify(attr));
				daoColumn.setAd_table_id(tableId);
				daoColumn.setIsactive("Y");
				daoColumn.setCreated(new Date());
				daoColumn.setUpdated(new Date());
				daoColumn.setEntitytype("M");
				BigDecimal relementId = saveElement(em, daoColumn);
				daoColumn.setAd_element_id(relementId);

				DAO_Ad_reference ref = new DAO_Ad_reference();
				referenceId = referenceId.add(new BigDecimal(1));
				ref.setAd_reference_id(referenceId);
				ref.setIsactive("Y");
				daoColumn.setAd_reference_id(referenceId);
				ref.setCreated(new Date());
				ref.setUpdated(new Date());
				ref.setEntitytype("M");
				daoColumn.setIskey("N");
				if(model.isPrimaryColumn(columnName)){
					daoColumn.setIskey("Y");
				}
				daoColumn.setIsparent("N");
				daoColumn.setIsmandatory("N");
				daoColumn.setIsupdateable("Y");
				daoColumn.setIsidentifier("N");
				daoColumn.setIstranslated("N");
				daoColumn.setIsencrypted("N");
				daoColumn.setIsselectioncolumn("N");
				daoColumn.setIsalwaysupdateable("Y");
				daoColumn.setIsautocomplete("N");


				if(isIDcolumn(attr, model)){
					ref.setName("ID");
					daoColumn.setIskey("Y");
					daoColumn.setIsmandatory("Y");
					daoColumn.setIsupdateable("N");
				}
				else if(hasOneColumn(attr, model)){
					ref.setName("Table Direct");
					daoColumn.setIsmandatory("Y");
				}
				else if(dt.equals("java.lang.String")){
					ref.setName("String");
					if((attr.toLowerCase().startsWith("is") || attr.toLowerCase().startsWith("has"))){
						ref.setName("Yes-No");
					}
					if(columnName.equals("name")){
						daoColumn.setIsidentifier("Y");
					}
				}
				else if(dt.equals("java.lang.Boolean")){
					ref.setName("Yes-No");
				}
				else if(dt.equals("java.lang.Integer")){
					ref.setName("Integer");
				}else if(dt.equals("java.math.BigDecimal")){
					ref.setName("Amount");
				}else if(dt.equals("java.util.UUID")){
					ref.setName("UUID");
				}else if(dt.equals("java.util.Date")){
					ref.setName("Date");
				}else if(dt.equals("java.lang.Long")){
					ref.setName("Integer");	
				}
				else{
					System.err.println(attr+" "+dt+" not found!");
				}

				DAO_Ad_reference refEx = DAO_Ad_reference.cast(em.getOne(new DAO_Ad_reference(), 
						new Filter("name", Filter.EQUAL, ref.getName())));
				if(refEx != null){
					daoColumn.setAd_reference_id(refEx.getAd_reference_id());
				}else{
					em.insert(ref);
				}
				em.insert(daoColumn);
			}
			em.commitTransaction();
		}

	}


	private static BigDecimal saveElement(EntityManager em, DAO_Ad_column daoColumn) throws DatabaseException {
		String actualColumnName = daoColumn.getColumnname();
		String columnName = daoColumn.getName();
		DAO_Ad_element element = DAO_Ad_element.cast(em.getOne(new DAO_Ad_element(), 
				new Filter("columnname", Filter.EQUAL, actualColumnName)));
		if(element == null){
			elementId = elementId.add(new BigDecimal(1));
			element = new DAO_Ad_element();
			String prettyName = CStringUtils.beautify(columnName);
			element.setAd_element_id(elementId);
			element.setColumnname(actualColumnName);
			element.setName(prettyName);
			element.setPrintname(prettyName);
			element.setEntitytype("D");
			element.setCreated(new Date());
			element.setUpdated(new Date());
			element.setIsactive("Y");
			em.insert(element);
		}
		return element.getAd_element_id();
	}

	private static boolean isIDcolumn(String column, ModelDef model) {
		String[] attributes = model.getPrimaryAttributes();
		for(int i = 0; i < attributes.length; i++){
			String attr = attributes[i];
			if(attr.equals(column)){
				return true;
			}
		}
		return false;
	}

	static boolean hasOneColumn(String column, ModelDef model){
		String[] fcolumns = model.getHasOneForeignColumn();
		for(String fc : fcolumns){
			if(fc.equals(column)){
				return true;
			}
		}
		return false;
	}


}
